import logging

from appium.webdriver.common.touch_action import TouchAction
from selenium.webdriver import ActionChains
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import TimeoutException
from selenium.webdriver.support.wait import WebDriverWait
from Common.driver_util import DriverUtils, DriverType


class BasePage:
    def __init__(self, driver_type):
        self.driver = DriverUtils.get_driver(driver_type)

    def find_el(self, *locator):
        try:
            el = WebDriverWait(self.driver, 10, 1).until(
                EC.presence_of_element_located(locator)
            )
            logging.info(f"元素 {locator} 定位成功")
            return el
        except TimeoutException:
            logging.error(f"元素未找到: {locator}")
            return None

    def find_els(self, *locator):
        try:
            el = WebDriverWait(self.driver, 10, 1).until(
                EC.presence_of_all_elements_located(locator)
            )
            logging.info(f"元素 {locator} 定位成功")
            return el
        except TimeoutException:
            logging.error(f"元素未找到: {locator}")
            return None

        # 输入文本

    def input_text(self, el, key_text):
        """
        向指定元素输入文本
        :param el: 元素对象
        :param key_text: 输入的文本
        :return: 操作是否成功的布尔值
        """
        try:
            # 模拟清除
            el.clear()
            logging.info(f"清除 {el} 的文本成功")
            # 模拟输入
            el.send_keys(key_text)
            logging.info(f"向 {el} 输入 {key_text} 成功")
            return True
        except Exception as e:
            logging.error(f"向 {el} 输入 {key_text} 失败: {str(e)}")
            return False

    # 截图
    def screenshot(self, file_path):
        """
        对当前页面进行截图并保存到指定路径
        :param file_path: 保存截图的文件路径
        :return: 操作是否成功的布尔值
        """
        try:
            self.driver.save_screenshot(file_path)
            logging.info(f"截图成功，保存路径: {file_path}")
            return True
        except Exception as e:
            logging.error(f"截图失败，保存路径: {file_path}, 错误信息: {str(e)}")
            return False

    # 对指定元素区域截图
    def el_screenshot(self, el, file_path):
        """
        对指定元素区域进行截图并保存到指定路径
        :param el: 要截图的元素对象
        :param file_path: 保存截图的文件路径
        :return: 操作是否成功的布尔值
        """
        try:
            el.screenshot(file_path)
            logging.info(f"元素区域截图成功，保存路径: {file_path}")
            return True
        except Exception as e:
            logging.error(f"元素区域截图失败，保存路径: {file_path}, 错误信息: {str(e)}")
            return False

    # 判断元素是否存在
    def is_el_exist(self, *locator):
        """
        判断指定 xpath 的元素是否存在
        :param xpath: 元素的 xpath 字符串
        :return: 元素是否存在的布尔值
        """
        try:
            WebDriverWait(self.driver, 10, 1).until(
                EC.presence_of_element_located(locator)
            )
            return True
        except TimeoutException:
            return False


class BuyerBasePage(BasePage):

    def __init__(self):
        super().__init__(DriverType.SELENIUM)
        self.mouse = ActionChains(self.driver)

    def switch_window(self, n):
        """
        切换到指定索引的窗口
        :param n: 切换到第几个窗口,整型
        :return: 操作是否成功的布尔值
        """
        try:
            # 获取句柄
            handles = self.driver.window_handles
            # 切换窗口
            self.driver.switch_to.window(handles[n])
            # 打印日志
            logging.info(f"成功切换到第 {n} 个窗口")
            return True
        except Exception as e:
            logging.error(f"切换到第 {n} 个窗口失败: {str(e)}")
            return False

    # frame切换
    def switch_frame(self, el):
        """
        切换到指定的 <iframe> 标签
        :param el: <iframe> 标签的元素对象
        :return: 操作是否成功的布尔值
        """
        try:
            # 切换指定iframe标签
            self.driver.switch_to.frame(el)
            # 打印日志
            logging.info(f"成功切换到 {el} iframe")
            return True
        except Exception as e:
            # 打印日志
            logging.error(f"切换到 {el} iframe 失败: {str(e)}")
            return False

    # 鼠标单击操作
    def mouse_click(self, element):
        """
        单击元素
        :param element: 要单击的元素
        """
        try:
            self.mouse.click(element).perform()
            logging.info(f"成功单击元素: {element}")
        except Exception as e:
            logging.error(f"单击操作失败: {e}")

    # 鼠标双击操作
    def mouse_double_click(self, element):
        """
        双击元素
        :param element: 要双击的元素
        """
        try:
            self.mouse.double_click(element).perform()
            logging.info(f"成功双击元素: {element}")
        except Exception as e:
            logging.error(f"双击操作失败: {e}")

    # 鼠标悬停操作
    def mouse_hover(self, element):
        """
        鼠标悬停在元素上
        :param element: 要悬停的元素
        """
        try:
            self.mouse.move_to_element(element).perform()
            logging.info(f"成功将鼠标悬停在元素: {element}")
        except Exception as e:
            logging.error(f"鼠标悬停操作失败: {e}")

    # 鼠标拖动操作
    def mouse_drag_and_drop(self, source_element, target_element):
        """
        拖动元素到目标元素位置
        :param source_element: 源元素
        :param target_element: 目标元素
        """
        try:
            self.mouse.drag_and_drop(source_element, target_element).perform()
            logging.info(f"成功将元素 {source_element} 拖动到 {target_element}")
        except Exception as e:
            logging.error(f"拖动操作失败: {e}")


class AppBasePage(BasePage):

    def __init__(self):
        super().__init__(DriverType.APPIUM)
        self.action = TouchAction(self.driver)

    # 长按操作
    def long_press(self, element, duration: int = 1000):
        try:
            self.action.long_press(element, duration=duration).perform()
            logging.info(f"成功长按元素 {element}，持续时间: {duration} 毫秒")
            return True
        except Exception as e:
            logging.error(f"长按操作失败: {str(e)}")
            return False

    # 轻敲操作
    def tap(self, element):
        try:
            self.action.tap(element).perform()
            logging.info(f"成功轻敲元素 {element}")
            return True
        except Exception as e:
            logging.error(f"轻敲操作失败: {str(e)}")
            return False

    # 拖拽操作
    def drag_and_drop(self, source_element, target_element):
        try:
            self.action.long_press(source_element).move_to(target_element).release().perform()
            logging.info(f"成功将元素 {source_element} 拖动到 {target_element}")
            return True
        except Exception as e:
            logging.error(f"拖动操作失败: {str(e)}")
            return False

